package com.kssoft.ebd.spider.common;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;

/**
 * @author liwu
 * @since 2025/6/19
 */
public class MyHttpUtils {

    public static void main(String[] args) {
        // 准备参数
        Map<String, Object> jsonParams = new HashMap<>();
        jsonParams.put("id", 123);
        jsonParams.put("name", "John Doe");

// 调用API并绕过HTTPS验证
        try {
            String response = callApiWithCookies(
                    "https://baidu.com",
                    "GET",
                    null,
                    null,
                    null,
                    ParamType.JSON,
                    true // 启用不安全的HTTPS连接
            );
            System.out.println(response);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 发送HTTP/HTTPS请求（支持GET/POST）并携带Cookie
     * @param apiUrl 请求URL
     * @param method 请求方法（GET/POST）
     * @param cookies Cookie信息
     * @param headers 自定义请求头
     * @param params 请求参数（支持多种类型）
     * @param paramType 参数类型（FORM/JSON/XML/RAW）
     * @param insecureHttps 是否忽略HTTPS证书验证（用于自签名证书或测试环境）
     * @return API响应内容
     */
    public static String callApiWithCookies(String apiUrl, String method,
                                             Map<String, String> cookies,
                                             Map<String, String> headers,
                                             Map<String, Object> params,
                                             ParamType paramType,
                                             boolean insecureHttps) throws Exception {

        // 构建Cookie字符串
        StringBuilder cookieHeader = new StringBuilder();
        if(cookies != null) {
            for (Map.Entry<String, String> entry : cookies.entrySet()) {
                if (cookieHeader.length() > 0) {
                    cookieHeader.append("; ");
                }
                cookieHeader.append(entry.getKey()).append("=").append(entry.getValue());
            }
        }

        // 创建URL
        URL url = new URL(apiUrl);

        // 处理HTTPS连接并忽略证书验证
        if (insecureHttps && "https".equalsIgnoreCase(url.getProtocol())) {
            // 创建信任所有证书的SSL上下文
            TrustManager[] trustAllCerts = new TrustManager[] {
                    new X509TrustManager() {
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                            // 信任所有客户端证书
                        }
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                            // 信任所有服务器证书
                        }
                    }
            };

            // 创建SSL上下文并初始化
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());

            // 设置默认的SSLSocketFactory和HostnameVerifier
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
        }

        // 打开连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        try {
            // 设置请求方法
            connection.setRequestMethod(method);

            // 设置通用请求头
            connection.setRequestProperty("Cookie", cookieHeader.toString());
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36");
            connection.setRequestProperty("Accept", "*/*");
            connection.setRequestProperty("Connection", "keep-alive");

            // 设置自定义请求头
            if (headers != null) {
                for (Map.Entry<String, String> header : headers.entrySet()) {
                    connection.setRequestProperty(header.getKey(), header.getValue());
                }
            }

            // 处理请求参数
            if (params != null && !params.isEmpty()) {
                connection.setDoOutput(true);

                // 根据参数类型设置Content-Type
                switch (paramType) {
                    case FORM:
                        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                        String formParams = buildFormParams(params);
                        try (OutputStream os = connection.getOutputStream()) {
                            os.write(formParams.getBytes(StandardCharsets.UTF_8));
                        }
                        break;

                    case JSON:
                        connection.setRequestProperty("Content-Type", "application/json");
                        String jsonParams = buildJsonParams(params);
                        try (OutputStream os = connection.getOutputStream()) {
                            os.write(jsonParams.getBytes(StandardCharsets.UTF_8));
                        }
                        break;

                    case XML:
                        connection.setRequestProperty("Content-Type", "application/xml");
                        // 假设params中包含完整XML字符串
                        String xmlParams = (String) params.get("xml");
                        try (OutputStream os = connection.getOutputStream()) {
                            os.write(xmlParams.getBytes(StandardCharsets.UTF_8));
                        }
                        break;

                    case RAW:
                        // 自定义原始数据
                        String contentType = (String) params.get("contentType");
                        String rawData = (String) params.get("data");
                        if (contentType != null) {
                            connection.setRequestProperty("Content-Type", contentType);
                        }
                        try (OutputStream os = connection.getOutputStream()) {
                            os.write(rawData.getBytes(StandardCharsets.UTF_8));
                        }
                        break;
                }
            }

            // 发送请求并获取响应
            int responseCode = connection.getResponseCode();
            System.out.println("API请求 [" + method + "] " + apiUrl + " 状态码: " + responseCode);

            // 读取响应内容
            InputStream inputStream;
            if (responseCode >= 200 && responseCode < 300) {
                inputStream = connection.getInputStream();
            } else {
                inputStream = connection.getErrorStream();
            }

            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                return response.toString();
            }

        } finally {
            connection.disconnect();
        }
    }

    // 参数类型枚举
    public enum ParamType {
        FORM, JSON, XML, RAW
    }

    // 构建表单参数
    private static String buildFormParams(Map<String, Object> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            if (result.length() > 0) {
                result.append("&");
            }
            result.append(URLEncoder.encode(entry.getKey(), String.valueOf(StandardCharsets.UTF_8)));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue().toString(), String.valueOf(StandardCharsets.UTF_8)));
        }
        return result.toString();
    }

    // 构建JSON参数（简化实现）
    private static String buildJsonParams(Map<String, Object> params) {
        StringBuilder json = new StringBuilder("{");
        boolean first = true;

        for (Map.Entry<String, Object> entry : params.entrySet()) {
            if (!first) {
                json.append(",");
            }

            json.append("\"").append(entry.getKey()).append("\":");

            Object value = entry.getValue();
            if (value instanceof String) {
                json.append("\"").append(value).append("\"");
            } else {
                json.append(value);
            }

            first = false;
        }

        json.append("}");
        return json.toString();
    }
}
